#include <stdlib.h>
#include "utils/list.h"

void addFirst(struct EsdlLinkedListElement ** list_ptr, void * data) {
    struct EsdlLinkedListElement * element = malloc(sizeof * element);
    element->next = NULL;
    element->previous = NULL;
    element->data = data;

    if (*list_ptr != NULL) {
        (*list_ptr)->previous = element;
        element->next = *list_ptr;
    }

    *list_ptr = element;
}

void addLast(struct EsdlLinkedListElement ** list_ptr, void * data) {
    struct EsdlLinkedListElement * element = malloc(sizeof * element);
    element->next = NULL;
    element->previous = NULL;
    element->data = data;

    if (*list_ptr == NULL) {
        *list_ptr = element;
        return;
    }

    struct EsdlLinkedListElement * element_tmp = *list_ptr;
    while (element_tmp->next != NULL) {
        element_tmp = element_tmp->next;
    }
    element_tmp->next = element;
    element->previous = element_tmp;
}

void * removeFirst(struct EsdlLinkedListElement ** list_ptr) {
    if (list_ptr == NULL)
        return NULL;

    void * data = (*list_ptr)->data;
    struct EsdlLinkedListElement * element_tmp = (*list_ptr)->next;
    element_tmp->previous = NULL;
    free(*list_ptr);
    *list_ptr = element_tmp;

    return data;
}

void * removeLast(struct EsdlLinkedListElement ** list_ptr) {
    if (list_ptr == NULL)
        return NULL;

    struct EsdlLinkedListElement * element_tmp = *list_ptr;
    while (element_tmp->next != NULL) {
        element_tmp = element_tmp->next;
    }

    void * data = (*list_ptr)->data;
    element_tmp->previous->next = NULL;
    free(element_tmp);

    return data;
}

void removeElement(struct EsdlLinkedListElement ** list_ptr, void * data) {
    if (list_ptr == NULL)
        return;

    struct EsdlLinkedListElement * element_tmp = *list_ptr;
    while (element_tmp != NULL) {
        if (element_tmp->data == data) {
            (element_tmp->previous != NULL) ? (element_tmp->previous->next = element_tmp->next) : (*list_ptr = element_tmp->next);
            if (element_tmp->next != NULL) element_tmp->next->previous = element_tmp->previous;
            free(element_tmp);
        } else {
            element_tmp = element_tmp->next;
        }
    }
}
